package com.autocloud.filter;

import com.autocloud.model.Result;
import com.autocloud.model.security.DataFiltering;
import com.autocloud.util.ByteUtil;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.apache.commons.lang.StringUtils;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.regex.Pattern;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;

/**
 * http response 数据过滤
// */
@Component
public class RespBodyDataFilteringFilter implements GlobalFilter, Ordered {



    private static final List<MediaType> JsonContentTypes = Arrays.asList(APPLICATION_JSON, APPLICATION_JSON_UTF8);
    Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();

    @Override
    public int getOrder() {
        return -3;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        Object requestBody = exchange.getAttribute("cachedRequestBodyObject");
        final String url = exchange.getRequest().getURI().getRawPath();

        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                MediaType contentType = getHeaders().getContentType();
                if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux && JsonContentTypes.contains(contentType)) {
                    // http response 数据过滤
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

                        List<byte[]> byteList = new ArrayList<>();
                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            byteList.add(content);
                        });
                        String responseBody = null;
                        try {
                            responseBody = ByteUtil.toString(byteList);
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                            return bufferFactory().wrap(gson.toJson(Result.oflost("业务执行错误！", 201), Result.class).getBytes());
                        }
                        return bufferFactory().wrap(responseBody.getBytes());
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

}